package org.csu.pm.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.csu.pm.common.BaseResponse;
import org.csu.pm.common.ErrorCode;
import org.csu.pm.common.ResultUtils;
import org.csu.pm.entity.User;
import org.csu.pm.entity.Userinfo;
import org.csu.pm.exception.BusinessException;
import org.csu.pm.mapper.UserMapper;
import org.csu.pm.model.dto.LoginBody;
import org.csu.pm.model.dto.RegisterBody;
import org.csu.pm.model.dto.UpdatePhoneBody;
import org.csu.pm.model.vo.UserVO;
import org.csu.pm.service.UserService;
import org.csu.pm.service.UserinfoService;
import org.csu.pm.util.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author kwanho
 * @description 针对表【user】的数据库操作Service实现
 * @createDate 2022-11-11 20:16:25
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private UserinfoService userinfoService;

    @Override
    public BaseResponse<?> register(RegisterBody loginBody) {
        // 1. 解析出所有的参数
        Long stuNo;
        try {
            stuNo = Long.valueOf(loginBody.getStuNo());
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "学号必须为数字");
        }
        String password = loginBody.getPassword();
        String realName = loginBody.getRealName();
        String email = loginBody.getEmail();
        String phone = loginBody.getPhone();
        // 2. 校验参数
        if (StringUtils.isAnyBlank(password, realName, email, phone)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "参数不能为空");
        }
        // 3. 校验学号是否已经存在
        User sameUser = this.getOne(new QueryWrapper<User>().eq("stu_no", stuNo));
        if (sameUser != null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "学号已经存在");
        }
        // 4. 保存用户
        User newUser = new User();
        newUser.setStu_no(stuNo);
        newUser.setPassword(EncryptUtil.encode(password));
        Userinfo newUserinfo = new Userinfo();
        newUserinfo.setStu_no(stuNo);
        newUserinfo.setReal_name(realName);
        newUserinfo.setEmail(email);
        newUserinfo.setPhone(phone);
        try {
            this.save(newUser);
            userinfoService.save(newUserinfo);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SAVE_ERROR, "注册失败，请稍候重试");
        }
        // 5. 生成token
        Long regUserID = this.getOne(new QueryWrapper<User>().eq("stu_no", stuNo)).getId();
        String token = jwtUtil.createJwtToken(Long.toString(regUserID), JwtUtil.DEFAULT);
        // 5. 返回结果
        UserVO userVO = new UserVO(token, newUserinfo);
        return ResultUtils.success(userVO);
    }

    @Override
    public BaseResponse<?> login(LoginBody loginBody) {
        // 1. 解析出用户名和密码
        String stuNo = loginBody.getStuNo();
        String password = loginBody.getPassword();
        // 2. 校验参数合法性
        if (StringUtils.isAnyBlank(stuNo, password)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "用户名或密码为空");
        }
        // 3. 根据用户名查询用户信息
        User loginUser = this.getOne(new QueryWrapper<User>().eq("stu_no", stuNo));
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }
        if (!EncryptUtil.match(password, loginUser.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码错误");
        }
        // 4. 生成token
        String token = jwtUtil.createJwtToken(Long.toString(loginUser.getId()), JwtUtil.DEFAULT);
        // 5. 返回结果
        Userinfo loginUserinfo = userinfoService.getOne(new QueryWrapper<Userinfo>().eq("stu_no", loginUser.getStu_no()));
        UserVO userVO = new UserVO(token, loginUserinfo);
        return ResultUtils.success(userVO);
    }

    @Override
    public User getSafeUser(User user) {
        User safetyUser = user.clone();
        safetyUser.setPassword(null);
        return safetyUser;
    }

    @Override
    public BaseResponse<?> getCaptcha(Long userId, String phone) {
        // 1. 校验手机号是否为空
        if (StringUtils.isBlank(phone)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "手机号不能为空");
        }
        // 2. 校验手机号的合法性
        if (!RegexUtil.matchPhone(phone)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "手机号格式不正确");
        }
        // 3. 校验手机号是否已经被注册
        Userinfo sameUser = userinfoService.getOne(new QueryWrapper<Userinfo>().eq("phone", phone));
        if (sameUser != null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "手机号已经被注册");
        }
        // 4. 生成验证码
        String captcha = RandomUtil.randomNumbers(6);
        // 5. 将验证码存入redis
        redisUtil.set(userId + "@" + phone, captcha, 5, TimeUnit.MINUTES);
        // 6. 发送验证码
        SmsUtil.sendCaptcha(phone, captcha);
        // 7. 返回结果
        return ResultUtils.success(null);
    }

    @Override
    public BaseResponse<?> updatePhone(Long userId, UpdatePhoneBody updatePhoneBody) {
        // 1. 解析出手机号和验证码
        String phone = updatePhoneBody.getPhone();
        String captcha = updatePhoneBody.getCaptcha();
        // 2. 校验参数合法性
        if (StringUtils.isAnyBlank(phone, captcha)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "手机号或验证码为空");
        }
        // 3. 校验手机号的合法性
        if (!RegexUtil.matchPhone(phone)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "手机号格式不正确");
        }
        // 4. 校验手机号是否已经被注册
        Userinfo sameUser = userinfoService.getOne(new QueryWrapper<Userinfo>().eq("phone", phone));
        if (sameUser != null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "手机号已经被注册");
        }
        // 5. 校验验证码是否正确
        String redisCaptcha = (String) redisUtil.get(userId + "@" + phone);
        if (!captcha.equals(redisCaptcha)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码错误或已过期");
        }
        // 6. 更新手机号
        Userinfo updateUserinfo = new Userinfo();
        updateUserinfo.setPhone(phone);
        try {
            userinfoService.update(updateUserinfo, new QueryWrapper<Userinfo>().eq("stu_no", userId));
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.UPDATE_ERROR, "更新手机号失败，请稍候重试");
        }
        // 7. 返回结果
        return ResultUtils.success(phone);
    }

    @Override
    public BaseResponse<?> deleteAccount(Long userId) {
        // 1. 删除用户详情
        try {
            userinfoService.remove(new QueryWrapper<Userinfo>().eq("stu_no", this.getById(userId).getStu_no()));
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DELETE_ERROR, "删除用户失败，请稍候重试");
        }
        // 2. 删除用户
        try {
            this.removeById(userId);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.DELETE_ERROR, "删除用户失败，请稍候重试");
        }
        // 3. 返回结果
        return ResultUtils.success("用户已被注销");
    }

    @Override
    public BaseResponse<?> getAccountInfo(Long userId) {
        // 1. 查询用户详情
        Userinfo userinfo = userinfoService.getOne(new QueryWrapper<Userinfo>().eq("stu_no", this.getById(userId).getStu_no()));
        // 2. 返回结果
        return ResultUtils.success(userinfo);
    }
}




